﻿using System;
using System.Collections.Generic;

namespace Snake.FSM
{
    public sealed class FsmState<TStateKey, TOwner>
    {
        private Dictionary<FsmCondition<TOwner>, TStateKey> _conditionMaps;

        private Action<TOwner> _enterHandle;
        private Action<TOwner> _exitHandle;
        private Action<TOwner> _updateHandle;

        public void BindEnterAction(Action<TOwner> action)
        {
            _enterHandle = action;
        }

        public void BindUpdateAction(Action<TOwner> action)
        {
            _updateHandle = action;
        }

        public void BindExitAction(Action<TOwner> action)
        {
            _exitHandle = action;
        }

        public void AddCondition(FsmCondition<TOwner> condition, TStateKey stateName)
        {
            if (condition == null)
            {
                return;
            }

            _conditionMaps ??= new Dictionary<FsmCondition<TOwner>, TStateKey>();

            _conditionMaps.Add(condition, stateName);
        }

        public void RemoveCondition(FsmCondition<TOwner> condition)
        {
            if (_conditionMaps == null || condition == null)
            {
                return;
            }

            _conditionMaps.Remove(condition);
        }

        public bool CheckCondition(TOwner owner, out TStateKey stateName)
        {
            if (_conditionMaps == null)
            {
                stateName = default;
                return false;
            }

            foreach (var condition in _conditionMaps.Keys)
            {
                if (!condition.Condition(owner))
                {
                    continue;
                }

                stateName = _conditionMaps[condition];
                return true;
            }

            stateName = default;
            return false;
        }

        public void OnEnter(TOwner owner)
        {
            _enterHandle?.Invoke(owner);
        }

        public void OnUpdate(TOwner owner)
        {
            _updateHandle?.Invoke(owner);
        }

        public void OnExit(TOwner owner)
        {
            _exitHandle?.Invoke(owner);
        }
    }
}